#pragma once
#include <ft2build.h>
#include <freetype/freetype.h>
#include <freetype/ftstroke.h>
#include <vector>
#include <map>
#ifdef _MSC_VER
#define MIN __min
#define MAX __max
#else
#define MIN std::min
#define MAX std::max
#endif
namespace CnyeCPlus{
	namespace FType{
		union PixelRGBA
		{
			PixelRGBA()
				: integer(0) { }
			PixelRGBA(uint8 bi, uint8 gi, uint8 ri, uint8 ai = 255)
			{
				b = bi;
				g = gi;
				r = ri;
				a = ai;
			}

			uint32 integer;

			struct
			{
				uint8 r, g, b, a;
			};
		};
		struct Span
		{
			Span() { }
			Span(int _x, int _y, int _width, int _coverage)
				: x(_x), y(_y), width(_width), coverage(_coverage) { }

			int x, y, width, coverage;
		};
		class GlyphSpans;
		class Spans:public std::vector<Span>{
		public:
			GlyphSpans* gs;
		};
		class GlyphSpans{
		public:
			GlyphSpans(){
				xmin=xmax=ymin=ymax=0;
				this->NSpans.gs=this;
				this->OSpans.gs=this;
			}
		public:
			wchar_t c;
			Spans NSpans;
			Spans OSpans;
			float xmin,xmax,ymin,ymax;
			void Include(float x,float y)
			{
				xmin = MIN(xmin, x);
				ymin = MIN(ymin, y);
				xmax = MAX(xmax, x);
				ymax = MAX(ymax, y);
			}
			float Width() const { return xmax - xmin + 1; }
			float Height() const { return ymax - ymin + 1; }
			int RGBA(unsigned char** buf,PixelRGBA foreground,PixelRGBA background);
		};

		public ref class FreeType sealed 
		{
			/*private:
			Windows::UI::Color _Background,_Foreground;
			public:
			property Windows::UI::Color Background{
			Windows::UI::Color get(){
			return this->_Background;
			}

			void set(Windows::UI::Color val){
			this->_Background=val;
			}
			}
			property Windows::UI::Color Foreground{
			Windows::UI::Color get(){
			return this->_Foreground;
			}

			void set(Windows::UI::Color val){
			this->_Foreground=val;
			}
			}*/
		public:
			FreeType(const Platform::Array<unsigned char>^ fontbuf);
			virtual ~FreeType(void);
			void SetCharSize(
				float char_width,float char_height,
				unsigned int horz_resolution,unsigned int vert_resolution);
			void SetCharSize(float char_size){
				this->SetCharSize(char_size,char_size,90,90);
			}
			Windows::Foundation::Size GenerateGlyph(wchar_t c,float outlineWidth);
			Windows::Foundation::Size GenerateGlyph(wchar_t c){
				return this->GenerateGlyph(c,3.0f);
			}
			//Platform::Array<byte>^ CharGlyph(wchar_t c);

		internal:
			FreeType(unsigned char *fbuf,unsigned int fbufSize);
			void Init(unsigned char *fbuf,unsigned int fbufSize);
			//int CharGlyph(wchar_t c,byte** buf,float outlineWidth);
			GlyphSpans* LoadGlyph(wchar_t c,float outlineWidth);
			GlyphSpans* LoadGlyph(wchar_t c){
				return this->LoadGlyph(c,3.0f);
			}
			void AddGlyph(GlyphSpans* gs);
			GlyphSpans* GetGlyph(wchar_t c);
			void FreeGlyph(wchar_t c);
			ID2D1Bitmap1* CreateBitmap(
				ID2D1DeviceContext* context,IWICImagingFactory* factory,
				wchar_t c,Windows::UI::Color tcolor,Windows::UI::Color bcolor);
			void FreeBitmap();

			static void RenderSpans(FT_Library &library,FT_Outline * const outline,Spans *spans);
			static void RasterCallback(const int y,const int count,const FT_Span * const spans,void * const user);
			//
		private:
			FT_Library library;
			FT_Face face;
			std::vector<GlyphSpans*> LoadedGlyph;
			std::map<wchar_t,ID2D1Bitmap1*> Bitmaps;
			float charSize;
		};
	}
}
